home *** CD-ROM | disk | FTP | other *** search
/ Mission 3 / Mission 3.zip / Mission 3.iso / texte / qed / src / sort.c < prev    next >
C/C++ Source or Header  |  1998-09-29  |  8KB  |  343 lines

  1. #include "global.h"
  2. #include "block.h"
  3. #include "edit.h"
  4. #include "memory.h"
  5. #include "rsc.h"
  6. #include "text.h"
  7. #include "window.h"
  8.  
  9. #define    CMD_NONE    0
  10. #define    CMD_KRIT    1
  11. #define    CMD_SORT    2
  12.  
  13. static int        last_cmd = CMD_NONE,
  14.                     start_x = 0, end_x = 0;        /* Kriterium */
  15. static long        start_z = 0, end_z = 0;        /* Bereich */
  16. static ZEILEP    p1, p2;
  17. static bool        sort_down = FALSE;            /* FLASE: a..z  TRUE: z..a */
  18. static bool        sort_grkl = FALSE;            /* Groß vor Klein */
  19.  
  20. /*
  21.  * Die nationalen Sonderzeichen werden auf die entsprechenden Vokale umgemappt
  22.  * und somit direkt hinter sie sortiert.
  23.  * Die Idee stammt aus dem Modul 'Strings' der MM2-Lib von Thomas Tempelmann.
  24. */
  25. static char    sort_tab[] = 
  26. {
  27.     0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
  28.     0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
  29.     0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
  30.     0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
  31.     0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
  32.     0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
  33.     0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
  34.     0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
  35.     'C','u','e','a','a','a','a','c','e','e','e','i','i','i','A','A',
  36.     'E','a','A','o','o','o','u','u','y','O','U',0x9B,0x9C,0x9D,'s',0x9F,
  37.     'a','i','o','u','n','N','a','o',0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
  38.     'a','o','O','o','o','O','A','A','O',0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
  39.     'i','I',0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
  40.     0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
  41.     0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
  42.     0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF
  43. };
  44.  
  45.  
  46. static int qed_strncmp(char *s1, char *s2, int n, bool grkl)
  47. {
  48.     register char    c1, c2;
  49.     register long    count;
  50.  
  51.     if (!s1)
  52.         return s2 ? -1 : 0;
  53.     
  54.     if (!s2) 
  55.         return 1;
  56.  
  57.     count = n;
  58.     do 
  59.     {
  60.         c1 = *s1++; 
  61.         c2 = *s2++; 
  62.         if (!grkl)
  63.         {
  64.             c1 = nkc_toupper(c1);
  65.             c2 = nkc_toupper(c2);
  66.         }
  67.     } 
  68.     while (--count >= 0 && c1 && c1 == c2);
  69.  
  70.     if (count < 0)
  71.         return(0);
  72.  
  73.     if (c1 == c2)
  74.         return 0;
  75.     else if (c1 == '\0')
  76.         return -1;
  77.     else if (c2 == '\0')
  78.         return 1;
  79.     else
  80.         return (sort_tab[c1] - sort_tab[c2]);
  81. }
  82.  
  83.  
  84. static int laufcmp(ZEILEP l1, ZEILEP l2)
  85. {
  86.     int    n;
  87.     
  88.     if (start_x == 0 && end_x == 0)            /* ganze Zeilen vergleichen */
  89.     {
  90.         return qed_strncmp(TEXT(l1), TEXT(l2), l1->len, sort_grkl);
  91.     }
  92.     else                                                /* nur teilweise vergleichen */
  93.     {
  94.         /* Zeile kürzer als Kriterium-Start? */
  95.         if (l2->len < start_x)
  96.             return 1;
  97.  
  98.         /* Zeile kürzer als Kriterium-Länge? */
  99.         if (l2->len < end_x)
  100.             n = l2->len - start_x + 1;
  101.         else
  102.             n = end_x - start_x + 1;
  103.  
  104.         return qed_strncmp(TEXT(l1) + start_x, TEXT(l2) + start_x, n, sort_grkl);
  105.     }
  106. }
  107.  
  108.  
  109. /*
  110.  * Langsam, aber dafür optimal simpel: Insertion Sort.
  111. */
  112. static void insert_sort(RINGP r, ZEILEP ins)
  113. {
  114.     ZEILEP    col, lauf;
  115.  
  116.     lauf = LAST(r);
  117.     if (sort_down)
  118.         while (!IS_FIRST(lauf) && (laufcmp(lauf, ins) < 0))
  119.             VORG(lauf);
  120.     else
  121.         while (!IS_FIRST(lauf) && (laufcmp(lauf, ins) > 0))
  122.             VORG(lauf);
  123.     
  124.     col = new_col(TEXT(ins), ins->len);
  125.     col_insert(lauf, col);
  126.     r->lines++;
  127. }
  128.  
  129. static void do_sort(TEXTP t_ptr, RINGP r)
  130. {
  131.     ZEILEP    start, ende, lauf;
  132.  
  133.     start = get_line(&t_ptr->text, start_z);
  134.     ende = get_line(&t_ptr->text, end_z);
  135.     init_textring(r);
  136.     lauf = start;
  137.     while (lauf != ende)
  138.     {
  139.         insert_sort(r, lauf);
  140.         NEXT(lauf);
  141.     }
  142.     /* erste, leere Zeile entfernen */
  143.     col_delete(r, FIRST(r));
  144.  
  145.     /* leere Zeile am Ende anhängen */
  146.     lauf = new_col("", 0);
  147.     col_append(r, lauf);
  148. }
  149.  
  150. static void clear_sort(void)
  151. {
  152.     last_cmd = CMD_NONE;
  153.     start_z = 0;
  154.     end_z = 0;
  155.     start_x = 0;
  156.     end_x = 0;
  157. }
  158.  
  159. void sort_block(TEXTP t_ptr)
  160. {
  161.     /* halbe Zeile markiert -> aufrunden zur nächsten */
  162.     if (!(last_cmd == CMD_KRIT) && (t_ptr->x2 > 0) && !(IS_LAST(t_ptr->p2)))
  163.     {
  164.         t_ptr->z2++;
  165.         t_ptr->p2 = t_ptr->p2->nachf;
  166.     }
  167.  
  168.     if ((t_ptr->z2 > t_ptr->z1 + 1) || (last_cmd == CMD_KRIT))
  169.     {
  170.         RING    r;
  171.         int    antw;
  172.         char    str[26];
  173.  
  174.         if (last_cmd == CMD_KRIT)
  175.         {
  176.             clear_info(t_ptr);
  177.             start_x = t_ptr->x1;
  178.             end_x = t_ptr->x2 - 1;
  179.         }
  180.         else
  181.         {
  182.             start_z = t_ptr->z1;
  183.             end_z = t_ptr->z2;
  184.             p1 = t_ptr->p1;
  185.             p2 = t_ptr->p2;
  186.         }
  187.         
  188.         set_state(sort, BSUP, SELECTED, !sort_down);
  189.         set_state(sort, BSDOWN, SELECTED, sort_down);
  190.         set_state(sort, BSGRKL, SELECTED, sort_grkl);
  191.  
  192.         sprintf(str, rsc_string(SZEILESTR), start_z, end_z);
  193.         str[24] = EOS;
  194.         set_string(sort, BSZEILEN, str);
  195.         sprintf(str, rsc_string(SSPALTSTR), start_x, end_x);
  196.         str[24] = EOS;
  197.         set_string(sort, BSSPALTEN, str);
  198.             
  199.         antw = simple_mdial(sort, 0) & 0x7fff;
  200.         switch (antw)
  201.         {
  202.             case BSKRIT :
  203.                 last_cmd = CMD_KRIT;
  204.                 set_info(t_ptr, rsc_string(SKRITSTR));
  205.                 make_chg(t_ptr->link, POS_CHANGE, 0);
  206.                 break;
  207.             
  208.             case BSORT :
  209.                 last_cmd = CMD_SORT;
  210.                 break;
  211.             
  212.             case BSABBRUCH :
  213.                 clear_sort();
  214.                 break;
  215.         }
  216.         set_state(sort, antw, SELECTED, FALSE);
  217.         if (last_cmd == CMD_SORT)
  218.         {
  219.             sort_down = get_state(sort, BSDOWN, SELECTED);
  220.             sort_grkl = get_state(sort, BSGRKL, SELECTED);
  221.  
  222.             do_sort(t_ptr, &r);
  223.             
  224.             /* ursprünglichen Block wieder herstellen und ersetzen */
  225.             t_ptr->z1 = start_z;
  226.             t_ptr->z2 = end_z;
  227.             t_ptr->x1 = 0;
  228.             t_ptr->x2 = 0;
  229.             t_ptr->p1 = p1;
  230.             t_ptr->p2 = p2;
  231.             blk_paste(t_ptr, &r);
  232.             kill_textring(&r);
  233.             clear_sort();
  234.         }
  235.         restore_edit();
  236.     }
  237.     else
  238.         note(1, 0, SORTERR);
  239. }
  240.  
  241.  
  242. /* --------------------------------------------------------------------------- */
  243. #if 0
  244. static int line_cmp(char *z1, int l1, char *z2, int l2)
  245. {
  246.     int     l = -1;
  247.     bool    quit = FALSE;
  248.     
  249.     if (l1 != l2)
  250.         l = l1;
  251.     else
  252.     {
  253.         l = 0;
  254.         while (!quit)
  255.         {
  256.             if (l > l1)
  257.             {
  258.                 l = l1;
  259.                 quit = TRUE;
  260.             }
  261.             if (l > l2)
  262.             {
  263.                 l = l2;
  264.                 quit = TRUE;
  265.             }
  266.             if (!quit && z1[l] != z2[l])
  267.                 quit = TRUE;
  268.             if (!quit)
  269.                 l++;
  270.         }
  271.     }
  272.     /* normaler Durchlauf, kein Unterschied */
  273.     if (l == l1 && l == l2)
  274.         l = -1;
  275.     return l;
  276. }
  277.  
  278. static void mark_diff(TEXTP t_ptr, int z, int s)
  279. {
  280.     t_ptr->xpos = s;
  281.     if (z >= t_ptr->text.lines - 1)
  282.         t_ptr->ypos = t_ptr->text.lines - 2;
  283.     else    
  284.         t_ptr->ypos = z;
  285.     
  286.     blk_mark(t_ptr, 0);
  287.     if (IS_LAST(t_ptr->cursor_line))
  288.         t_ptr->xpos = t_ptr->cursor_line->len;
  289.     else
  290.     {
  291.         t_ptr->xpos = 0;
  292.         NEXT(t_ptr->cursor_line);
  293.         t_ptr->ypos++;
  294.     }
  295.     blk_mark(t_ptr, 1);
  296.     restore_edit();
  297. }
  298.  
  299. void compare(TEXTP t1, TEXTP t2)
  300. {
  301.     if (t1 && t2)
  302.     {
  303.         ZEILEP    lauf1, lauf2;
  304.         bool        quit = FALSE;
  305.         int        l, z1, z2;
  306.  
  307.         blk_demark(t1);
  308.         blk_demark(t2);
  309.         restore_edit();
  310.         lauf1 = FIRST(&t1->text);
  311.         lauf2 = FIRST(&t2->text);
  312.         quit = (!lauf1 || !lauf2);
  313.         z1 = 0;
  314.         z2 = 0;
  315.         while (!quit)
  316.         {
  317.             l = line_cmp(TEXT(lauf1), lauf1->len, TEXT(lauf2), lauf2->len);
  318.             if (l != -1)
  319.             {
  320.                 debug("Zeile: %d, %d\n", z, l);
  321.                 t1->cursor_line = lauf1;
  322.                 mark_diff(t1, z1, l);
  323.                 t2->cursor_line = lauf2;
  324.                 mark_diff(t2, z2, l);
  325.                 pos_korr(get_window(t1->link), t1);
  326.                 pos_korr(get_window(t2->link), t2);
  327. quit = (do_walert(1, 2, "[1][Unterschied gefunden!][Weiter|Ende]", " qed ") == 2);
  328.             }
  329.             NEXT(lauf1);
  330.             z1++;
  331.             NEXT(lauf2);
  332.             z2++;
  333.             if (IS_TAIL(lauf1) || IS_TAIL(lauf2))
  334.             {
  335.                 Bconout(2, 7);
  336.                 quit = TRUE;
  337.             }
  338.         }
  339.     }
  340. }
  341.  
  342. #endif
  343.